package owlapps2012.owlToSql.events.p4;

import java.awt.event.ActionEvent;
import java.io.File;
import java.util.Set;
import org.apache.log4j.Logger;
import org.protege.editor.owl.model.inference.OWLReasonerManager;
import org.protege.editor.owl.model.inference.ReasonerStatus;
import org.protege.editor.owl.model.inference.ReasonerUtilities;
import org.protege.editor.owl.ui.action.ProtegeOWLAction;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.reasoner.InferenceType;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import owlapps2012.owlToSql.base.DynamicAppConfig;
import owlapps2012.owlToSql.base.OwlToSqlTransformationException;
import owlapps2012.owlToSql.events.EventsTransformer;


public class EventsToSQLP4Transformer extends ProtegeOWLAction
{

	private static final long serialVersionUID = -1239374784081176791L;
	private static final String configFileName = EventsToSQLP4Transformer.class.getSimpleName().concat(".properties");
	private static Logger log = Logger.getLogger(EventsToSQLP4Transformer.class);
	private String jarDirectory;
	private DynamicAppConfig lfToSQLConfig;


	@Override
	public void initialise() throws Exception 
	{
		this.jarDirectory = new File(EventsToSQLP4Transformer.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath();
		try 
		{
			this.lfToSQLConfig = new DynamicAppConfig(jarDirectory.concat(File.separator).concat(configFileName));
		} 
		catch (Exception e) 
		{
			throw new Exception("Unable to read configuration file: "+jarDirectory.concat(File.separator).concat(configFileName), e);
		}
	}


	@Override
	public void dispose() throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void actionPerformed(ActionEvent e)
	{
		/*
		 * Obtain/create annotation property for writing SQL queries currentOntology:sqlSelect
		 * Find relevant OWL classes (Get all subclasses of Event)
		 * Transform every equivalent class expr into SQL and writing that query into an annotation (removing any existing currentOntology:sqlSelect and andding new ones)
		 * 
		 */
		
		OWLOntology activeOntology =  getOWLModelManager().getActiveOntology();
		OWLAnnotationProperty sqlSelectAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#sqlSelect")));
		OWLReasonerManager reasonerManager = getOWLModelManager().getOWLReasonerManager();
        ReasonerUtilities.warnUserIfReasonerIsNotConfigured(getOWLWorkspace(), reasonerManager);
        OWLReasoner reasoner = reasonerManager.getCurrentReasoner();
        reasoner.precomputeInferences(new InferenceType[0]);
        
        OWLClass lastSelectedClass = getOWLWorkspace().getOWLSelectionModel().getLastSelectedClass();
        if (lastSelectedClass != null && reasonerManager.getReasonerStatus() == ReasonerStatus.INITIALIZED) 
        {
            Set<OWLClass> classesToTranslate = reasoner.getSubClasses(lastSelectedClass, false).getFlattened();
            classesToTranslate.add(lastSelectedClass);
            EventsTransformer et;
			try
			{
				et = new EventsTransformer(lfToSQLConfig);
			} 
			catch (Exception e2)
			{
				log.error("Error while loading configuration.", e2);
				return;
			}
            for (OWLClass classToTranslate : classesToTranslate) 
            {
            	if(classToTranslate.isOWLNothing())
            		continue;
            	
            	Set<OWLClassExpression> eces = classToTranslate.getEquivalentClasses(activeOntology);
            	if(eces.size()>1)
            	{
            		log.warn("Transformation cancelled - cause: more than one definition of category: "+classToTranslate);
            		return;
            	}
            	
            	for(OWLClassExpression ece : eces)
            	{
            		String basicSql;
					try 
					{
						basicSql = et.transformOWLClassExpression(ece);
					} 
					catch (OwlToSqlTransformationException e1) 
					{
						log.error("Problem during transformation of "+classToTranslate+" - unable to transform following definition: "+ece, e1);
						continue;
					}
            		
            		for(OWLAnnotationAssertionAxiom anAxiom : classToTranslate.getAnnotationAssertionAxioms(activeOntology))
            		{
            			if(anAxiom.getProperty().equals(sqlSelectAP))
            				activeOntology.getOWLOntologyManager().removeAxiom(activeOntology, anAxiom);
            		}
            		
            		activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(classToTranslate.getIRI(), getOWLDataFactory().getOWLAnnotation(sqlSelectAP, getOWLDataFactory().getOWLLiteral(basicSql)))));
            	}
            }
        }
		
	}

}
